package org.wattdepot.cli.commands;

import java.util.ArrayList;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.resource.source.jaxb.Source;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Provides the total power generated from a specific source and fuel type.
 * @author Paul Galiza
 *
 */
public class TotalPowerCommand implements Command {

  /**
   * Calls the listTotalPower method.
   * 
   * @param userInput The user input.
   * @param client The WattDepotClient
   * @return Returns the method call with the proper parameters.
   */
  public String doCommand(List<String> userInput, WattDepotClient client) {
    return listTotalPower(userInput, client);
  }

  /**
   * Returns a string information of the total power.
   * 
   * @param commandParam The input from user.
   * @param client The WattDepotClient
   * @return Returns the total power information.
   */
  private String listTotalPower(List<String> commandParam, WattDepotClient client) {
    StringBuffer buff = new StringBuffer();
    
    //Retrieves the source, timestamp and fuel type information
    String source = commandParam.get(1);
    String timeStamp = commandParam.get(2);
    String fuelType = commandParam.get(4);
    
    
    //Checks to see if source is valid
    SourceChecker check = new SourceChecker();
    if (!check.sourceChecker(source, client)) {
      return "Invalid Source";
    }
    
    //Checks to see if time stamp is valid
    TStampChecker tstampCheck = new TStampChecker();
    if (!tstampCheck.checkTStamp(timeStamp)) {
      return "Invalid timestamp";
    }
    long sum = 0;
    try {
      Source theSource = client.getSource(source);
      XMLGregorianCalendar tstamp = Tstamp.makeTimestamp(timeStamp);
      
      
      List<String> foo = fuelSourceList(theSource, fuelType, client);
      for (String string : foo) {
        sum += client.getPowerGenerated(string, tstamp);
      }
      
    }
    catch (NotAuthorizedException e) {
      e.printStackTrace();
    }
    catch (ResourceNotFoundException e) {
      e.printStackTrace();
    }
    catch (BadXmlException e) {
      e.printStackTrace();
    }
    catch (MiscClientException e) {
      e.printStackTrace();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    buff.append(sum);
    return buff.toString();
  }
  
  /**
   * Recursive method that returns a list of all the sources 
   * and each of its sub sources.
   * 
   * @param source User inputed source.
   * @param fueltype User inputed fueltype.
   * @param client The WattDepot client.
   * @return Returns a list of all the sources and sub sources.
   */
  private List<String> fuelSourceList(Source source, String fueltype, WattDepotClient client) {
    List<String> mainList = new ArrayList<String>();

    try {
      //Retrieve the sub sources if source is virtual
      if (source.isVirtual()) {
        //sub sources list
        List<String> subsources = source.getSubSources().getHref();
        for (String list : subsources) {
          //Splits the sub-sources URL with '/' as delimiter
          String[] split = list.split("/");
          
          //adds all the recursed list to the main list
          mainList.addAll(fuelSourceList(client.getSource(split[5]), fueltype, client));
        }
      }
      else {
        //The subsequent non-virtual sources
        //checks for the specified fuel type
        if (source.getProperty("fuelType").equals(fueltype)) {
          mainList.add(source.getName());
        }
      }
    }
    catch (NotAuthorizedException e) {
      e.printStackTrace();
    }
    catch (ResourceNotFoundException e) {
      e.printStackTrace();
    }
    catch (BadXmlException e) {
      e.printStackTrace();
    }
    catch (MiscClientException e) {
      e.printStackTrace();
    }

    return mainList;
  }
}
